home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
os2
/
timidsrc.zip
/
wav2pat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-20
|
8KB
|
345 lines
/*
Wav2pat -- simple WAVE to GUS patch converter
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
This is a little tool to convert RIFF WAVEs to GUS-compatible
patches. A WAVE is read from stdin, and a GUS patch is written to
stdout.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef SOLARIS
#include <string.h>
#else
#include <strings.h>
#endif
#include "config.h"
#include "instrum.h"
#define DEFAULT_NOTE 60
#define DEFAULT_ROOT 261626
int32 freq_table[128]=
{
8176, 8662, 9177, 9723,
10301, 10913, 11562, 12250,
12978, 13750, 14568, 15434,
16352, 17324, 18354, 19445,
20602, 21827, 23125, 24500,
25957, 27500, 29135, 30868,
32703, 34648, 36708, 38891,
41203, 43654, 46249, 48999,
51913, 55000, 58270, 61735,
65406, 69296, 73416, 77782,
82407, 87307, 92499, 97999,
103826, 110000, 116541, 123471,
130813, 138591, 146832, 155563,
164814, 174614, 184997, 195998,
207652, 220000, 233082, 246942,
261626, 277183, 293665, 311127,
329628, 349228, 369994, 391995,
415305, 440000, 466164, 493883,
523251, 554365, 587330, 622254,
659255, 698456, 739989, 783991,
830609, 880000, 932328, 987767,
1046502, 1108731, 1174659, 1244508,
1318510, 1396913, 1479978, 1567982,
1661219, 1760000, 1864655, 1975533,
2093005, 2217461, 2349318, 2489016,
2637020, 2793826, 2959955, 3135963,
3322438, 3520000, 3729310, 3951066,
4186009, 4434922, 4698636, 4978032,
5274041, 5587652, 5919911, 6271927,
6644875, 7040000, 7458620, 7902133,
8372018, 8869844, 9397273, 9956063,
10548082, 11175303, 11839822, 12543854
};
int main(int argc, char **argv)
{
int32
note=DEFAULT_NOTE,
root=DEFAULT_ROOT,
verbosity=0,
samplerate=-1,
datasize=-1,
junklength, c;
int
infd=STDIN_FILENO;
unsigned char
thing[4096],
*point,
modes=0;
while ((c=getopt(argc, argv, "r:n:v"))>0)
switch(c)
{
case 'r': root=atol(optarg); break;
case 'n': root=freq_table[atoi(optarg) & 127]; break;
case 'u': note=atol(optarg); break;
case 'v': verbosity++; break;
default: return 1;
}
if (optind==argc-1)
{
if ((infd=open(argv[optind], O_RDONLY))<0)
{
perror("wav2pat: I can't open your WAVE");
return 3;
}
}
else if (optind!=argc)
{
fprintf(stderr,
"Usage: wav2pat [-r RootFreq | -n Note] [-u Note] [-v] [filename]\n");
return 1;
}
/* check out the putative RIFF WAVE on stdin */
if (read(infd, thing, 12)<=0)
{
perror("wav2pat: I can't read your WAVE");
return 3;
}
if (memcmp(thing, "RIFF", 4) || memcmp(thing+8, "WAVE", 4))
{
fprintf(stderr, "wav2pat: I want a RIFF WAVE on stdin!\n");
return 2;
}
while (datasize==-1)
{
if (read(infd, thing, 8)!=8)
{
perror("wav2pat: "
"Your WAVE ran out before I got to the interesting bits");
return 3;
}
junklength=LE_LONG(*((int32 *)(thing+4)));
/* This Microsoft file format is designed to be impossible to
parse correctly if one doesn't have the full specification.
If you have a wave with an INFO "chunk", you lose. Thank you
for playing. */
if (!memcmp(thing, "fmt ", 4))
{
if (junklength > 4096)
{
fprintf(stderr, "wav2pat: "
"WAVEs with %ld-byte format blocks make me throw up!\n",
junklength);
return 2;
}
if (read(infd, thing, junklength) != junklength)
{
perror("wav2pat: Your WAVE is mangled");
return 3;
}
if (LE_SHORT(*((int16 *)(thing))) != 1)
{
fprintf(stderr, "wav2pat: I don't understand your WAVE. "
"It has a type %d format chunk!\n",
LE_SHORT(*((int16 *)(thing))));
return 2;
}
if (LE_SHORT(*((int16 *)(thing + 2))) != 1)
{
fprintf(stderr, "wav2pat: This WAVE has %d channels! "
"There can be only one!\n",
LE_SHORT(*((int16 *)(thing + 2))));
return 2;
}
samplerate=LE_LONG(*((int32 *)(thing + 4)));
switch(LE_SHORT(*((int16 *)(thing + 14))))
{
case 8: modes |= MODES_UNSIGNED; break;
case 16: modes |= MODES_16BIT; break;
default:
fprintf(stderr, "wav2pat: Ack! Ppthbth! %d-bit samples!",
LE_SHORT(*((int16 *)(thing + 14))));
return 2;
}
if (verbosity)
fprintf(stderr, "wav2pat: This is a %d-bit, %ld Hz WAVE\n",
(LE_SHORT(*((int16 *)(thing + 14)))),
samplerate);
}
else if (!memcmp(thing, "data", 4))
{
if (samplerate==-1)
{
fprintf(stderr, "wav2pat: Your WAVE has no format information before data!\n");
return 2;
}
if (verbosity)
fprintf(stderr, "wav2pat: It has %ld bytes of data\n", junklength);
datasize=junklength;
}
else
{
if (verbosity)
fprintf(stderr, "wav2pat: "
"Your WAVE has a %ld-byte chunk called `%4.4s'\n",
junklength, thing);
/* It's cool to pad chunks with NULs to align them on
half-word boundaries. */
if (junklength & 1)
junklength++;
while (junklength>0)
{
if ((c=read(infd, thing, (junklength>4096) ? 4096 : junklength))
<= 0)
{
perror("wav2pat: Now your WAVE has run out of data");
return 3;
}
junklength -= c;
}
}
}
/* hammer together something that looks like a GUS patch header */
#define pound(a) *point++=(a);
#define pounds(a) { *((int16 *)point)=LE_SHORT(a); point+=2; }
#define poundl(a) { *((int32 *)point)=LE_LONG(a); point+=4; }
#define bounce(a) point += a;
memset(thing, 0, 335);
point=thing;
/* header */
memcpy(point, "GF1PATCH110", 12);
point += 12;
/* Gravis ID */
memcpy(point, "ID#000002", 10);
point += 10;
/* description */
strcpy(point, "Copyleft 1995 EWE&U Conductions and one Retreated Gravi\032");
point += 60;
pound(1); /* instruments */
pound(14); /* voices */
pound(0); /* channels */
pounds(1); /* waveforms */
pounds(127); /* master volume */
poundl(datasize); /* data size */
bounce(36); /* reserved */
pounds(1); /* instrument # */
strcpy(point, "Bleahnoise"); /* instrument name */
point += 16;
poundl(datasize); /* instrument size */
pound(1); /* layers */
bounce(40); /* reserved */
pound(0); /* layer duplicate */
pound(0); /* layer */
poundl(datasize); /* layer size */
pound(1); /* samples */
bounce(40); /* reserved */
strcpy(point, "bleah"); /* wave name */
point += 7;
pound(0); /* fractions */
poundl(datasize); /* wave size */
poundl(0); /* loop start */
poundl(datasize); /* loop end */
pounds(samplerate); /* sample rate */
poundl(8176); /* low freq */
poundl(12543854); /* high freq */
poundl(root); /* root freq */
pounds(512); /* tune */
pound(7); /* balance */
pound(63); /* envelope rates */
pound(63);
pound(63);
pound(63);
pound(63);
pound(63);
pound(240); /* envelope offsets */
pound(240);
pound(240);
pound(240);
pound(240);
pound(240);
pound(0); /* tremolo sweep */
pound(0); /* tremolo rate */
pound(0); /* tremolo depth */
pound(0); /* vibrato sweep */
pound(0); /* vibrato rate */
pound(0); /* vibrato depth */
pound(modes); /* modes */
pounds(note); /* scale freq */
pounds(1024); /* scale factor */
bounce(36); /* reserved */
write(STDOUT_FILENO, thing, 335);
/* wave data */
while (datasize>0)
{
if ((c=read(infd, thing, (datasize>4096) ? 4096 : datasize))
<= 0)
{
perror("wav2pat: I can't read data");
return 3;
}
write(STDOUT_FILENO, thing, c);
datasize -= c;
}
/* be courteous */
if (infd != STDIN_FILENO)
close(infd);
return 0;
}